/*
 * CPThread.cpp
 *
 *  Created on: 15/03/2011
 *      Author: nba
 */

#include "CPThread.h"
#include "State/RealTimeLoopState.h"
#include "State/ContinuousProcessing/Simulation.h"
#include "State/ContinuousProcessing/RealTimeExecution.h"
#include "State/ContinuousProcessing/Mode1.h"
#include "State/ContinuousProcessing/Mode2.h"
#include "State/ContinuousProcessing/Mode3.h"

#include "Strategy/InputStrategy.h"
#include "Strategy/SimulatedInputStrategy.h"
#include "Strategy/NonSimulatedInputStrategy.h"

#include "Strategy/OutputStrategy.h"
#include "Strategy/SimulatedOutputStrategy.h"
#include "Strategy/NonSimulatedOutputStrategy.h"

#include "Strategy/AlgorithmStrategy.h"
#include "Strategy/Mode1AlgorithmStrategy.h"
#include "Strategy/Mode2AlgorithmStrategy.h"
#include "Strategy/Mode3AlgorithmStrategy.h"

using namespace application;
using namespace continuousProcessing;

CPThread::CPThread(Context* ctx) {
	_context = ctx;
}

CPThread::~CPThread() {
	_context = 0;
}

void CPThread::run() {
	InputStrategy* iStrat = 0;
	SimulatedInputStrategy iSim;
	NonSimulatedInputStrategy iNonSim;

	OutputStrategy* oStrat = 0;
	SimulatedOutputStrategy oSim;
	NonSimulatedOutputStrategy oNonSim;

	AlgorithmStrategy* aStrat = 0;
	Mode1AlgorithmStrategy aMode1;
	Mode2AlgorithmStrategy aMode2;
	Mode3AlgorithmStrategy aMode3;

	while(true) {
		// Check if we are in the realtime state machine
		if( dynamic_cast<RealTimeLoopState *>(_context->getCurrentState()) ) {

			// Select input/output strategy from either simulated or real, depending on state
			if( dynamic_cast<Simulation *>(_context->getSecondaryState()) ) {
				iStrat = &iSim;
				oStrat = &oSim;
			} else { // realtime state
				iStrat = &iNonSim;
				oStrat = &oNonSim;
			}

			// Select algorithm based on mode state
			if( dynamic_cast<Mode1 *>(_context->getCurrentState()) ) {
				aStrat = &aMode1;
			} else if ( dynamic_cast<Mode2 *>(_context->getCurrentState()) ) {
				aStrat = &aMode2;
			} else if ( dynamic_cast<Mode3 *>(_context->getCurrentState()) ) {
				aStrat = &aMode3;
			}

			// Read input
			int input = iStrat->getInput();

			// Perform algorithm on input
			int output = aStrat->runAlgo(input, input);

			// Send to output
			oStrat->writeOutput(output);

		}

		sleep(500);
	}
}
